package cn.jingyuan.owl.utils.core.swing;

import cn.jingyuan.owl.utils.core.exceptions.UtilsException;
import cn.jingyuan.owl.utils.core.img.ImgUtils;
import cn.jingyuan.owl.utils.core.swing.clipboard.ClipboardUtils;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;

/**
 * {@link Robot} 封装工具类，提供截屏等工具。
 */
public class RobotUtils {

    private static final Robot ROBOT;

    private static int delay;

    static {
        try {
            ROBOT = new Robot();
        } catch (AWTException e) {
            throw new UtilsException(e);
        }
    }

    /**
     * 设置默认的延迟时间。 <br>
     * 当按键执行完后的等待时间，也可以用 ThreadUtil.sleep 方法代替。
     *
     * @param delayMillis 等待毫秒数
     */
    public static void setDelay(int delayMillis) {
        delay = delayMillis;
    }

    /**
     * 模拟鼠标移动
     *
     * @param x 移动到的 x 坐标
     * @param y 移动到的 y 坐标
     */
    public static void mouseMove(int x, int y) {
        ROBOT.mouseMove(x, y);
    }

    /**
     * 模拟单击 <br>
     * 鼠标单击包括鼠标左键的按下和释放
     */
    public static void click() {
        ROBOT.mousePress(InputEvent.BUTTON1_MASK);
        ROBOT.mouseRelease(InputEvent.BUTTON1_MASK);
        delay();
    }

    /**
     * 模拟右键单击 <br>
     * 鼠标单击包括鼠标右键的按下和释放
     */
    public static void rightClick() {
        ROBOT.mousePress(InputEvent.BUTTON1_MASK);
        ROBOT.mouseRelease(InputEvent.BUTTON1_MASK);
        delay();
    }

    /**
     * 模拟鼠标滚轮滚动
     *
     * @param wheelAmt 滚动数，负数表示向前滚动，正数向后滚动。
     */
    public static void mouseWheel(int wheelAmt) {
        ROBOT.mouseWheel(wheelAmt);
        delay();
    }

    /**
     * 模拟键盘点击。 <br>
     * 包括键盘的按下和释放。
     *
     * @param keyCodes 按键码列表，见 {@link KeyEvent}
     */
    public static void keyClick(int... keyCodes) {
        for (int keyCode : keyCodes) {
            ROBOT.keyPress(keyCode);
            ROBOT.keyRelease(keyCode);
        }
        delay();
    }

    /**
     * 打印输出指定字符串（借助剪贴板）
     *
     * @param str 字符串
     */
    public static void keyPressString(String str) {
        ClipboardUtils.setString(str);
        keyPressWithCtrl(KeyEvent.VK_V);// 粘贴
        delay();
    }

    /**
     * shift+ 按键
     *
     * @param key 按键
     */
    public static void keyPressWithShift(int key) {
        ROBOT.keyPress(KeyEvent.VK_SHIFT);
        ROBOT.keyPress(key);
        ROBOT.keyRelease(key);
        ROBOT.keyRelease(KeyEvent.VK_SHIFT);
        delay();
    }

    /**
     * ctrl+ 按键
     *
     * @param key 按键
     */
    public static void keyPressWithCtrl(int key) {
        ROBOT.keyPress(KeyEvent.VK_CONTROL);
        ROBOT.keyPress(key);
        ROBOT.keyRelease(key);
        ROBOT.keyRelease(KeyEvent.VK_CONTROL);
        delay();
    }

    /**
     * alt+ 按键
     *
     * @param key 按键
     */
    public static void keyPressWithAlt(int key) {
        ROBOT.keyPress(KeyEvent.VK_ALT);
        ROBOT.keyPress(key);
        ROBOT.keyRelease(key);
        ROBOT.keyRelease(KeyEvent.VK_ALT);
        delay();
    }

    /**
     * 截取全屏
     *
     * @return 截屏的图片
     */
    public static BufferedImage captureScreen() {
        return captureScreen(ScreenUtils.getRectangle());
    }

    /**
     * 截取全屏到文件
     *
     * @param outFile 写出到的文件
     *
     * @return 写出到的文件
     */
    public static File captureScreen(File outFile) {
        ImgUtils.write(captureScreen(), outFile);
        return outFile;
    }

    /**
     * 截屏
     *
     * @param screenRect 截屏的矩形区域
     *
     * @return 截屏的图片
     */
    public static BufferedImage captureScreen(Rectangle screenRect) {
        return ROBOT.createScreenCapture(screenRect);
    }

    /**
     * 截屏
     *
     * @param screenRect 截屏的矩形区域
     * @param outFile 写出到的文件
     *
     * @return 写出到的文件
     */
    public static File captureScreen(Rectangle screenRect, File outFile) {
        ImgUtils.write(captureScreen(screenRect), outFile);
        return outFile;
    }

    /**
     * 等待指定毫秒数
     */
    private static void delay() {
        if (delay > 0) {
            ROBOT.delay(delay);
        }
    }

}
